#pragma once

#include "../umlmodel_global.h"

#include <memory>
#include <vector>

#include "DeployedArtifact.h"
#include "DeploymentTarget.h"
#include "PackageableElement.h"

using std::make_shared;
using std::shared_ptr;
using std::vector;

namespace uml {
class Classifier;
class Slot;
class ValueSpecification;

/// <summary>
/// InstanceSpecification
/// An InstanceSpecification is a model element that represents an instance in a
/// modeled system. An InstanceSpecification can act as a DeploymentTarget in a
/// Deployment relationship, in the case that it represents an instance of a Node.
/// It can also act as a DeployedArtifact, if it represents an instance of an
/// Artifact.
/// </summary>
class UMLMODEL_EXPORT InstanceSpecification : public PackageableElement, public DeployedArtifact, public DeploymentTarget {

public: // Constructors and destructors
    explicit InstanceSpecification(const QString& umlType="uml::InstanceSpecification");

public: // JsonSerializable override
    void fromJson(const QJsonObject& json, QStringList& errorList) override;
    void toJson(QJsonObject& json) override;

public: // Properties
    /// <summary>
    /// classifiers getter
    /// The Classifier or Classifiers of the represented instance. If multiple
    /// Classifiers are specified, the instance is classified by all of them.
    /// </summary>
    vector<shared_ptr<Classifier>>& classifiers();

    /// <summary>
    /// slots2 getter
    /// A Slot giving the value or values of a StructuralFeature of the instance. An
    /// InstanceSpecification can have one Slot per StructuralFeature of its
    /// Classifiers, including inherited features. It is not necessary to model a Slot
    /// for every StructuralFeature, in which case the InstanceSpecification is a
    /// partial description.
    /// </summary>
    vector<shared_ptr<Slot>>& slots2();

    /// <summary>
    /// specification getter
    /// A specification of how to compute, derive, or construct the instance.
    /// </summary>
    shared_ptr<ValueSpecification> specification() const;

    /// <summary>
    /// specification setter
    /// A specification of how to compute, derive, or construct the instance.
    /// </summary>
    void setSpecification(shared_ptr<ValueSpecification> value);

private: // Fields
    /// <summary>
    /// classifiers
    /// The Classifier or Classifiers of the represented instance. If multiple
    /// Classifiers are specified, the instance is classified by all of them.
    /// </summary>
    vector<shared_ptr<Classifier>> classifiers_;

    /// <summary>
    /// slots2
    /// A Slot giving the value or values of a StructuralFeature of the instance. An
    /// InstanceSpecification can have one Slot per StructuralFeature of its
    /// Classifiers, including inherited features. It is not necessary to model a Slot
    /// for every StructuralFeature, in which case the InstanceSpecification is a
    /// partial description.
    /// </summary>
    vector<shared_ptr<Slot>> slots2_;

    /// <summary>
    /// specification
    /// A specification of how to compute, derive, or construct the instance.
    /// </summary>
    shared_ptr<ValueSpecification> specification_;

};

} // namespace uml
